#include "options.dlg.h"
#include "options.page.h"
#include "misc.h"

#include <QtWidgets/QtWidgets>

struct OptionsDlg::Priv {
	OptionsDlg* dlg;
	QBoxLayout* btnLayout;
	QStackedLayout* stackedLayout;
	QButtonGroup* btnGroup;
	OptionsPage* curPage;
	SessionState session_state;
	std::vector<OptionsPage*> pages;

	QPushButton* btnSaveDef;
	QPushButton* btnUseDef;
	QPushButton* btnApply;
	QPushButton* btnReset;

	void addPage(OptionsPage* p) {
		auto btn=new QRadioButton{p->name(), dlg};
		if(pages.empty()) {
			btn->setChecked(true);
			curPage=p;
		}
		pages.emplace_back(p);
		btnGroup->addButton(btn);
		btnLayout->addWidget(btn, 0);
		stackedLayout->addWidget(p);
		connect(btn, &QRadioButton::toggled,
				[this,p](bool c)->void { if(c) { chgPage(p); } });
		connect(p, &OptionsPage::stateChanged, dlg, &OptionsDlg::stateChanged);
	}
	void chgPage(OptionsPage* p) {
		stackedLayout->setCurrentWidget(p);
		curPage=p;
		curPage->setState(session_state);
	}
	Priv(OptionsDlg* d):
		dlg{d}, curPage{nullptr}, pages{}
	{
	}
	~Priv() {
		//for(auto p: pages)
			//delete p;
	}
};

OptionsDlg::OptionsDlg():
	QDialog{nullptr, 0},
	priv{new Priv{this}}
{
	auto vlayout=new QVBoxLayout(this);
	auto hlayout1=new QHBoxLayout();
	vlayout->addLayout(hlayout1, 1);
	auto hlayout2=new QHBoxLayout();
	vlayout->addLayout(hlayout2, 0);

	priv->btnSaveDef=new QPushButton(QIcon{":/images/breeze/document-save.svg"}, "&Save", this);
	hlayout2->addWidget(priv->btnSaveDef, 0);
	connect(priv->btnSaveDef, &QPushButton::clicked, this, &OptionsDlg::saveDefault);
	priv->btnUseDef=new QPushButton(QIcon{":/images/breeze/edit-clear.svg"}, "Use &Defaults", this);
	hlayout2->addWidget(priv->btnUseDef, 0);
	connect(priv->btnUseDef, &QPushButton::clicked, this, &OptionsDlg::useDefault);
	hlayout2->addStretch(1);
	priv->btnApply=new QPushButton(QIcon{":/images/breeze/dialog-ok.svg"}, "&Apply", this);
	hlayout2->addWidget(priv->btnApply, 0);
	connect(priv->btnApply, &QPushButton::clicked, this, &OptionsDlg::applyChanges);
	priv->btnReset=new QPushButton(QIcon{":/images/breeze/edit-undo.svg"}, "&Reset", this);
	hlayout2->addWidget(priv->btnReset, 0);
	connect(priv->btnReset, &QPushButton::clicked, this, &OptionsDlg::resetChanges);

	priv->btnLayout=new QVBoxLayout();
	hlayout1->addLayout(priv->btnLayout, 0);
	auto line=new QFrame(this);
	hlayout1->addWidget(line, 0);
	line->setFrameShape(QFrame::VLine);
	priv->stackedLayout=new QStackedLayout();
	hlayout1->addLayout(priv->stackedLayout, 1);

	priv->btnGroup=new QButtonGroup(this);
	priv->btnGroup->setExclusive(true);

	auto label=new QLabel{"Data", this};
	priv->btnLayout->addWidget(label, 0);
	priv->addPage(OptionsPage::cacheThreadOptions());
	priv->addPage(OptionsPage::sessionLoadingOptions());
	priv->addPage(OptionsPage::sessionChannelOptions());

	label=new QLabel{"Display", this};
	priv->btnLayout->addWidget(label, 0);
	priv->addPage(OptionsPage::viewerGeneralOptions());
	priv->addPage(OptionsPage::viewerColorOptions());
	priv->addPage(OptionsPage::viewerVolumeOptions());
	
	label=new QLabel{"Compute", this};
	priv->btnLayout->addWidget(label, 0);
	priv->addPage(OptionsPage::computeGeneralOptions());
	priv->addPage(OptionsPage::computeFindOptions());
	priv->addPage(OptionsPage::computeConnOptions());
	priv->addPage(OptionsPage::computeRefineOptions());
	priv->addPage(OptionsPage::computeRefineAutoOptions());

	priv->btnLayout->addStretch(1);
}
OptionsDlg::~OptionsDlg() {
	for(auto p: priv->pages) {
		priv->stackedLayout->removeWidget(p);
		p->setParent(nullptr);
	}
	delete priv;
}
void OptionsDlg::setState(SessionState s) {
	priv->session_state=s;
	if(priv->curPage)
		priv->curPage->setState(s);
}
void OptionsDlg::stateChanged(bool a, bool b, bool c, bool d) {
	if(sender()==priv->curPage) {
		priv->btnApply->setEnabled(a);
		priv->btnReset->setEnabled(b);
		priv->btnSaveDef->setEnabled(c);
		priv->btnUseDef->setEnabled(d);
	}
}
void OptionsDlg::useDefault() {
	if(priv->curPage) {
		priv->curPage->useDefault();
	}
}
void OptionsDlg::saveDefault() {
	if(priv->curPage) {
		priv->curPage->saveDefault();
	}
}
void OptionsDlg::applyChanges() {
	if(priv->curPage) {
		priv->curPage->applyChanges();
	}
}
void OptionsDlg::resetChanges() {
	if(priv->curPage) {
		priv->curPage->resetChanges();
	}
}
void OptionsDlg::dumpOptions(Options* opt) {
	//for(auto p: priv->pages) {
		//p->saveSettings(opt);
	//}
}

OptionsDlg* OptionsDlg::_instance{nullptr};
